/**
  ******************************************************************************
  * @file    Demo/src/main.c 
  * @author  MCD Application Team
  * @version V1.0.0
  * @date    10/29/2010
  * @brief   Main program body
  ******************************************************************************
  * @copy
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2010 STMicroelectronics</center></h2>
  */ 

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_conf.h"
#include "Interrupts.h"
#include "Buttons.h"
#include "Clock.h"
#include "MotionControl.h"
#include "Robot.h"
#include "Display.h"
#include "Sound.h"

int __errno = 0;

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private consts ------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/
static __IO uint32_t __delay;

/* Private function prototypes -----------------------------------------------*/
void _Refresh();
void _Delay(uint32_t nTime);
void _OnSysTick(void);

/* Private functions ---------------------------------------------------------*/
int main(void)
{
	//Setup the microcontroller system. Initialize the Embedded Flash Interface,
	//initialize the PLL and update the SystemFrequency variable.
	SystemInit();

    Clock_Init();

    /* Setup SysTick Timer for 1 msec interrupts  */
    SysTick_Config(SystemCoreClock / 1000);
    Interrupts_RegisterCallback(INTERRUPTS_SysTick, _OnSysTick);

    _Delay(1000);

    /* Initialise other modules ------------------------------------------------*/
    Buttons_Init();
    MotionControl_Init();
    Display_Init();
    Sound_Init();

    Display_EnableAlarm(FALSE);

    Display_SetState(DISPLAY_Calibrating);
    Robot_BeginCalibration();
    while (!Buttons_IsPressed(BUTTONS_Blue))
    {
    	Display_Update();
    	Robot_UpdateCalibration();
    }
    Robot_EndCalibration();

    //Clock_SetNextState();
    Clock_SetTime(0);
    Clock_SetAlarm(0);

    while (TRUE)
    {
    	Display_SetState(DISPLAY_SettingTime);
    	_Delay(100);

    	// await release
    	while (Buttons_IsPressed(BUTTONS_Blue))
    	{
    		_Refresh();
    	}

    	uint32_t oldtime, time = ((Clock_GetTime() / 60) % (24 * 60)) * 60;
    	uint32_t alarm = ((Clock_GetAlarm() / 60) % (24 * 60)) * 60;
    	while (!Buttons_IsPressed(BUTTONS_Blue))
    	{
    		bool anypressed = FALSE;
    		if (Buttons_IsPressed(BUTTONS_LeftRed))
    		{
    			uint16_t hour = alarm / 3600;
    			uint16_t minute = (alarm % 3600) / 60;
    			if (Buttons_IsPressed(BUTTONS_LeftBlack))
    			{
    				hour = (hour + 1) % 24;
    				anypressed = TRUE;
    			}
    			if (Buttons_IsPressed(BUTTONS_RightBlack))
    			{
    				minute = (minute + 1) % 60;
    				anypressed = TRUE;
    			}

    			alarm = hour * 3600 + minute * 60;
    			Display_SetTime(alarm);
    		}
    		else
    		{
    			uint16_t hour = time / 3600;
    			uint16_t minute = (time % 3600) / 60;
				if (Buttons_IsPressed(BUTTONS_LeftBlack))
				{
					hour = (hour + 1) % 24;
					anypressed = TRUE;
				}
				if (Buttons_IsPressed(BUTTONS_RightBlack))
				{

					minute = (minute + 1) % 60;
					anypressed = TRUE;
				}

				time = hour * 3600 + minute * 60;
				Display_SetTime(time);
    		}
    		if (anypressed)
    		{
    			Display_Update();
    			_Delay(250); // debounce & limit repeat
    		}

    		_Refresh();
    	}

    	if (time != oldtime)
    	{
    	    Clock_SetTime(time);
    	}
    	Clock_SetAlarm(alarm);

    	Clock_SetNextState();
    	Display_SetState(DISPLAY_Normal);

    	while (Clock_GetState() == CLOCK_Running)
    	{
    		_Delay(100); // debounce
			while (Buttons_IsPressed(BUTTONS_Blue))
			{
				_Refresh();
			}

			// await press
			while (!Buttons_IsPressed(BUTTONS_Blue))
			{
				if (Buttons_IsPressed(BUTTONS_RightRed))
				{
					Clock_ToggleAlarm();
					_Delay(100); // debounce
					while (Buttons_IsPressed(BUTTONS_RightRed))
					{
						_Refresh();
					}
				}

				_Refresh();
			}

        	Clock_SetNextState();
    	}
    }
}

void _Refresh()
{
	Display_Update();
	Robot_Calculate();
}

void _OnSysTick(void)
{
    if (__delay != 0x00)
    {
        __delay--;
    }
}

void _Delay(__IO uint32_t time)
{
    __delay = time;

    while(__delay != 0);
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif

/**
  * @}
  */

/**
  * @}
  */

/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/
